package org.listbeast.core.filters.algorithms;

import java.util.HashSet;

import org.apache.log4j.Logger;
import org.listbeast.core.dataobjects.Song;

public class GeneralMatchingAlgorithm implements SongMatchingAlgorithm {

	private final static Logger LOG = Logger.getLogger(GeneralMatchingAlgorithm.class);

	public boolean compareSongs(Song librarySong, Song youtubeSong) {
		
		String artistName = librarySong.getArtistName().toLowerCase();
		
		artistName = artistName.replaceAll("[_]", " ");

		String[] song1words = prepareSongTitle(artistName, librarySong.getTitle());

		String[] song2words = prepareSongTitle(artistName, youtubeSong.getTitle());

		if (matchStrings(song1words, song2words)) {
			return true;
		} else {
			return false;
		}
	}
	

	private String[] prepareSongTitle(String artistName, String theSongTitle) {

		HashSet<String> excludes = getWordsToExclude(artistName);

		String songTitle = theSongTitle.toLowerCase();

		// gia na afhsei ta omwnyma kommatia (e.g. Black Sabbath - black
		// sabbath)
		if (!songTitle.equals(artistName)) {
			// we do not want to replace all occurrences of the artistName. Only
			// one
			songTitle = songTitle.replaceFirst(artistName, "");
		}

		for (String exclude : excludes) {
			songTitle = songTitle.replaceAll(exclude, " ");
		}

		songTitle = songTitle.replaceAll("[^a-zA-Z_\\- ]+", "");
		songTitle = songTitle.replaceAll("[_\\-]+", " ");
		songTitle = songTitle.replaceAll("^[ ]+", "");
		LOG.debug("prepareSongTitle():" + songTitle);

		String[] words = songTitle.split("[ ]+");
		return words;
	}

	private HashSet<String> getWordsToExclude(String artistName) {
		HashSet<String> excludes = new HashSet<String>();
		excludes.add("\\Wfrom\\W");
		excludes.add("\\Wof\\W");
		excludes.add("\\Wand\\W");
		excludes.add("\\Wthe\\W");
		excludes.add("^the");
		return excludes;
	}

	private boolean matchStrings(String[] words1, String[] words2) {

		// value of threshold means that threshold per cent of words1 are in
		// words2
		// meaning that if threshold% of words1 are in words2 the strings are
		// equal
		double threshold;

		if (words1.length == 2) {
			threshold = 1;
		} else if (words1.length == 3) {
			threshold = 0.6;
		} else {
			threshold = 0.5;
		}

		int i = 0;
		for (int j = 0; j < words1.length; j++) {
			LOG.debug(words1[j]);
			for (int k = 0; k < words2.length; k++) {
				if (words1[j].equalsIgnoreCase(words2[k])) {
					i++;
					words2[k] = "";
					break;
				}
			}
		}

		double score = (double) i / words1.length;
		LOG.debug("Score: " + score + "! (i,words1)=(" + i + ","
				+ words1.length + ")");
		if (score >= threshold) {
			return true;
		} else
			return false;
	}
}
